package org.indexador.util.sax;

import java.io.*;
import java.sql.*;
import java.text.*;
import java.util.*;
import java.util.Date;

import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.store.*;
import org.apache.lucene.util.*;
import org.indexador.util.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class ManipuladorWikipediaSax extends DefaultHandler {
  private int total;
  private long inicio = System.currentTimeMillis();
  private String elementoAtual;
  private String username;
  private Timestamp timestamp;
  private String pageId;
  private String title;
  private StringBuilder texto = new StringBuilder();
  private FileWriter writer;
  private Collection<String> hierarquia = new ArrayList<String>();
  //
  IndexWriter iw;

  public void startDocument() throws SAXException {
    try {
      File arquivo = new File(Constantes.INDICE_WIKIPEDIA_SAX);
      Analyzer analisador = new StandardAnalyzer(Version.LUCENE_32);
      IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_32,
          analisador);
      Directory diretorio = FSDirectory.open(new File(
          Constantes.DIRETORIO_INDICE_WIKIPEDIA));
      iw = new IndexWriter(diretorio, config);
      //
      if (arquivo.exists()) {
        arquivo.delete();
      }
      writer = new FileWriter(arquivo);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void endDocument() throws SAXException {
    try {
      writer.close();
      iw.optimize();
      iw.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void startElement(String uri, String localName, String qName,
      Attributes attributes) throws SAXException {
    //
    hierarquia.add(qName);
    if (qName.equals("page")) {
      reiniciaVariaveis();
      total++;
      if (total % 100000 == 0) System.out.println("Parcial: " + total);
    } else if (qName.equals("id")
        && hierarquia.toArray()[hierarquia.size() - 2].equals("title")) {
      elementoAtual = "pageId";
    } else if (qName.equals("title")
        && hierarquia.toArray()[hierarquia.size() - 2].equals("page")) {
      elementoAtual = "pageTitle";
    } else if (qName.equals("timestamp")
        && hierarquia.toArray()[hierarquia.size() - 3].equals("revision")) {
      elementoAtual = "timestamp";
    } else if (qName.equals("username")) {// && hierarquia.contains("revision")) {
      elementoAtual = "username";
    } else if (qName.equals("text")) {
      if (hierarquia.contains("revision")) {
        elementoAtual = "texto";
      }
    } else {
      elementoAtual = "";
    }
    //
  }

  private void reiniciaVariaveis() {
    username = null;
    timestamp = null;
    pageId = null;
    title = null;
    texto = new StringBuilder();
  }

  @Override
  public void endElement(String arg0, String arg1, String qName)
      throws SAXException {
    if (qName.equals("page")) {
      hierarquia.clear();
      try {
        if (username == null || timestamp == null || pageId == null
            || title == null || texto.length() == 0) {
          System.out.println();
        }
        writer.write(pageId + "^" + title + "\n");
        //
        Document doc = new Document();
        doc.add(new Field("id", pageId, Field.Store.YES,
            Field.Index.NOT_ANALYZED));
        doc.add(new Field("dataRevisao", timestamp.toString(), Field.Store.YES,
            Field.Index.NOT_ANALYZED));
        if (username != null)
          doc.add(new Field("username", username, Field.Store.YES,
              Field.Index.NOT_ANALYZED));
        doc.add(new Field("title", title, Field.Store.YES,
            Field.Index.NOT_ANALYZED));
        doc.add(new Field("texto", texto.toString(), Field.Store.YES,
            Field.Index.ANALYZED));
        iw.addDocument(doc);
        //        iw.commit();
        //
        texto = new StringBuilder();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  public void characters(char[] ch, int start, int length) throws SAXException {
    String dados = String.valueOf(ch, start, length).trim();
    if (dados.length() == 0) return;
    if (elementoAtual.equals("pageId")) {
      pageId = dados;
    } else if (elementoAtual.equals("pageTitle")) {
      title = dados;
    } else if (elementoAtual.equals("username")) {
      username = dados;
    } else if (elementoAtual.equals("timestamp")) {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
      try {
        Date time = format.parse(dados);
        Timestamp timeStamp = new Timestamp(time.getTime());
        this.timestamp = timeStamp;
      } catch (ParseException e) {
        System.out.println(title);
        System.out.println(pageId);
        System.out.println(e.getLocalizedMessage());
      }
    } else if (elementoAtual.equals("texto")) {
      texto.append(dados);
    }
  }

  public int getTotal() {
    return total;
  }

  public long getTempoTotal() {
    return (System.currentTimeMillis() - inicio) / 1000;
  }
}
